package com.yzdg.user.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yzdg.common.enums.ErrorCode;
import com.yzdg.common.utils.ThrowUtils;
import com.yzdg.model.auth.dtos.AuthUserDTO;
import com.yzdg.model.user.dtos.AddScoreDTO;
import com.yzdg.model.user.dtos.updateUserDTO;
import com.yzdg.model.user.entitys.UserInfo;
import com.yzdg.model.user.vos.GetUserVO;
import com.yzdg.user.mapper.UserInfoMapper;
import com.yzdg.user.service.UserInfoService;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户信息表(UserInfo)表服务实现类
 *
 * @author 一只呆瓜
 */
@Service("userInfoService")
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Resource
    private RedisTemplate redisTemplate;

    private final String USER_SCORE_KEY = "user.score";

    private final String USER_RANK_KEY = "user.rank";

    /**
     * openfeign调用的登录方法
     */
    @Override
    public Long login(AuthUserDTO authUserDTO) {
        // 查询用户
        UserInfo one = lambdaQuery()
                .eq(UserInfo::getPhone, authUserDTO.getPhone())
                .one();
        if(one == null){
            // 未找到用户执行注册
            UserInfo userInfo = new UserInfo();
            BeanUtils.copyProperties(authUserDTO, userInfo);
            userInfo.setIsDeleted(0);
            userInfo.setNickname("数字奇人");
            save(userInfo);
            // 根据手机号查询刚刚注册的用户
            return lambdaQuery()
                    .eq(UserInfo::getPhone, authUserDTO.getPhone())
                    .one()
                    .getLeiId();
        }
        // 校验密码
        ThrowUtils.throwIf(!one.getPassword().equals(authUserDTO.getPassword()), ErrorCode.OPERATION_ERROR, "密码错误");
        return one.getLeiId();
    }

    /**
     * 根据id查询用户信息
     */
    @Override
    public GetUserVO getUserById(Long id) {
        UserInfo byId = getById(id);
        GetUserVO getUserVO = new GetUserVO();
        BeanUtils.copyProperties(byId, getUserVO);
        // 将id转为字符串，便于前端接收
        getUserVO.setLeiId(String.valueOf(id));
        return getUserVO;
    }

    /**
     * 更新用户信息
     */
    @Override
    public boolean updateUser(updateUserDTO updateUserDTO) {
        updateUserDTO.setLeiId(updateUserDTO.getLeiId());
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(updateUserDTO, userInfo);
        return updateById(userInfo);
    }

    @Override
    public Boolean sign(Long userId) {
        //首先拼接key
        String day =  DateFormatUtils.format(new Date(), "yyyyMMdd");
        String key = userId + "." +day;
        //redis中是否存在该key
        Boolean flag = redisTemplate.hasKey(key);
        if(flag){
            // 用户已签到
            return false;
        }else{
            //设置redis中的过期时间，凌晨0点清空；
            redisTemplate.opsForValue().set(key, day, getRefreshTime(), TimeUnit.SECONDS);
            return true;
        }
    }

    /**
     * 增加积分
     */
    @Override
    public void addScore(AddScoreDTO addScoreDTO) {
        String scoreKey = USER_SCORE_KEY + "." + addScoreDTO.getUserId();
        redisTemplate.opsForValue().increment(scoreKey, addScoreDTO.getScore());
        // 排行榜
        redisTemplate.opsForZSet().incrementScore(USER_RANK_KEY, addScoreDTO.getUserId(), addScoreDTO.getScore());
    }

    @Override
    public List<UserInfo> queryHighScore() {
        // 查询积分排行前10的用户
        Set<ZSetOperations.TypedTuple<Long>> set = redisTemplate.opsForZSet().reverseRangeWithScores(USER_RANK_KEY, 0, 9);
        if(CollectionUtils.isEmpty(set)){
            return Collections.emptyList();
        }
        // 获取用户id列表
        return set.stream().map(rank -> {
            UserInfo userInfo = new UserInfo();
            // 根据id查询用户基本信息
            UserInfo byId = getById(rank.getValue());
            BeanUtils.copyProperties(byId, userInfo);
            userInfo.setScore(rank.getScore().intValue());
            return userInfo;
        }).collect(Collectors.toList());
    }

    /**
     * 获取当前时间离明天凌晨还有多少时间
     */
    public int getRefreshTime(){
        Calendar calendar = Calendar.getInstance();
        int now = (int) (calendar.getTimeInMillis()/1000);
        calendar.add(Calendar.DATE, 1);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY , 0);
        return (int) (calendar.getTimeInMillis()/1000-now);
    }

}
